package com.icinfo.cloud.provider.common.zlb.service.impl;

import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.icinfo.cloud.provider.common.utils.BaseUtil;
import com.icinfo.cloud.provider.common.utils.DateUtil;
import com.icinfo.cloud.provider.common.zlb.dto.*;
import com.icinfo.cloud.provider.common.zlb.service.ZlbEntLoginService;
import com.icinfo.cloud.provider.common.zlb.utils.IrsEntSignRes;
import com.icinfo.cloud.provider.common.zlb.utils.IrsEntUtils;
import com.icinfo.cloud.provider.common.zlb.utils.SimpleDesUtils;
import com.icinfo.framework.common.web.Result;
import com.icinfo.framework.core.exception.BusinessException;
import com.icinfo.framework.core.service.support.MyBatisServiceSupport;
import com.icinfo.framework.tools.utils.Md5Utils;
import com.icinfo.framework.tools.utils.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.web.client.RestTemplateBuilder;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;
import org.springframework.web.client.RestTemplate;

import javax.annotation.PostConstruct;
import javax.servlet.http.HttpServletRequest;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.security.NoSuchAlgorithmException;
import java.util.LinkedHashMap;
import java.util.Map;

/**
 * 浙里办登录服务
 *
 * @author zhengqiang
 * @date 2023-02-07
 **/
@Service
public class ZlbEntLoginServiceImpl extends MyBatisServiceSupport implements ZlbEntLoginService {
    private Logger logger = LoggerFactory.getLogger(getClass());


    /****************************个人用户登录配置*****************************/
    @Value("${zww.personal.login.getUserInfoUrl}")
    private String getUserInfoUrl;
    @Value("${zww.personal.login.ticketValidationUrl}")
    private String ticketValidationUrl;

    @Value("${zww.zlbEnt.login.accessKey}")
    private String serviceCode;
    @Value("${zww.zlbEnt.login.secretKey}")
    private String serviceSecret;
    @Value("${zww.personal.jumpAddress.success}")
    private String jumpSuccess;
    @Value("${zww.personal.login.recird.head}")
    private String personalRecirdHead;

    @Value("${zww.personal.forwardUrl}")
    private String forwardUrl;

    /****************************法人接入登录配置*****************************/
    @Value("${zww.zlbEnt.login.accessTokenUrl}")
    private String accessTokenUrl;
    @Value("${zww.zlbEnt.login.getUserInfoUrl}")
    private String getEntUserInfoUrl;
    @Value("${zww.zlbEnt.login.appId}")
    private String appId;

    @Value("${isPrd}")
    private String isPrd;

    @Autowired
    private RestTemplateBuilder restTemplateBuilder;
    private RestTemplate restTemplate;



    @PostConstruct
    void init() {
        restTemplate = restTemplateBuilder.build();
    }

    /**
     * 描述： 获取法人登录信息
     *
     * @author: zhengqiang
     * @date: 2023/2/9
     * @param: ticketId
     * @return {@link Object}
     **/
    @Override
    public Object getLegalUser(String ticketId) {
        logger.info("单点登录票据:" + ticketId);
        String tokenByTicketId = getTokenByTicketId(ticketId);
        Map<String, String> userInfoByToken = getUserInfoByToken(tokenByTicketId);
        logger.info("法人用户信息:{}", userInfoByToken);
        return userInfoByToken;
    }



    @Override
    public String getPersonalRedirectUrl(HttpServletRequest request) throws UnsupportedEncodingException {
        //1、获取参数
        request.setCharacterEncoding("UTF-8");
        String ticket = request.getParameter("ticket");
        //具体事项页面地址 如http://aa.com/item?id=3232
        String sp = request.getParameter("sp");
        logger.info("获取票据和具体事项页面信息：ticket={},sp={}", ticket, sp);
        // 2、校验登录令牌，获取用户的登录信息
        JSONObject jsonObj = getUserInfo(ticket);

        String redirectUrl = null;
        if (null != jsonObj) {
            final String result = "result";
            if (0 == jsonObj.getIntValue(result)) {
                System.out.println("验证令牌并获取用户的登录信息接口返回数据：" + jsonObj);
                ZlbEntUserInfoDto userInfo = JSONObject.parseObject(jsonObj.toJSONString(), ZlbEntUserInfoDto.class);
                if (null != userInfo) {

                    Map<String, String> paramsMap = new LinkedHashMap<>();
                    paramsMap.put("userName", userInfo.getUsername());
                    paramsMap.put("userPhone", userInfo.getMobile());
                    paramsMap.put("userType", "personal");
                    paramsMap.put("idnum", userInfo.getIdnum());
                    paramsMap.put("pripid", userInfo.getIdnum());
                    paramsMap.put("userId", userInfo.getUserid());
                    String dataStr = SimpleDesUtils.desEncrypt(JSONObject.toJSONString(paramsMap));
                    String urlParams = personalRecirdHead + URLEncoder.encode(dataStr, "UTF8");
                    if (StringUtils.isNotBlank(sp)) {
                        redirectUrl = sp + urlParams;
                    } else {
                        redirectUrl = jumpSuccess + urlParams;
                    }
                } else {
                    //redirectUrl = jumpFail;
                    throw new BusinessException("获取用户的登录信息失败");
                }
            } else {
                System.out.println("验证令牌并获取用户的登录信息失败:" + jsonObj.getString("errmsg"));
                throw new BusinessException("验证令牌并获取用户的登录信息失败:" + jsonObj.getString("errmsg"));
            }
        } else {
            throw new BusinessException("票据验证失败");
        }
        return redirectUrl;
    }

    /**
     * 根据单点登录票据换取请求 token
     *
     * @param ticketId
     * @return
     */
    @Override
    public String getTokenByTicketId(String ticketId) {
        HttpHeaders headers = getHttpHeaders(accessTokenUrl);
        JSONObject body = new JSONObject();
        body.put("appId", appId);
        body.put("ticketId", ticketId);

        HttpEntity<Map<String, Object>> request = new HttpEntity<>(body, headers);

        ResponseEntity<String> stringResponseEntity = restTemplate.postForEntity(accessTokenUrl, request, String.class);
        return checkResponse(stringResponseEntity).getJSONObject("data").getString("accessToken");
    }

    /**
     * 基于 token 获取用户信息
     *
     * @param accessToken
     * @return
     */
    @Override
    public Map<String, String> getUserInfoByToken(String accessToken) {
        HttpHeaders headers = getHttpHeaders(getEntUserInfoUrl);
        JSONObject body = new JSONObject();
        body.put("token", accessToken);

        HttpEntity<Map<String, Object>> request = new HttpEntity<>(body, headers);

        ResponseEntity<String> stringResponseEntity = restTemplate.postForEntity(getEntUserInfoUrl, request, String.class);
        JSONObject dataJson = checkResponse(stringResponseEntity).getJSONObject("data");
        logger.info("dataJson:{}", dataJson);
        String userType = dataJson.getString("userType");
        System.out.println(userType);
        Map<String, String> paramsMap = new LinkedHashMap<>();
        if ("LEGAL_PERSON".equals(userType)) {
            JSONObject legalJson = dataJson.getJSONObject("legalPersonInfo");
            String uniCode = legalJson.getString("unifiedSocialId");
            paramsMap.put("uniCode", uniCode);
            paramsMap.put("userName", legalJson.getString("name"));
            paramsMap.put("userPhone", legalJson.getString("attnPhone"));
            paramsMap.put("userType", "legal");
            paramsMap.put("userId", legalJson.getString("corpId"));
        } else if ("PERSON".equals(userType)) {
            JSONObject personJson = dataJson.getJSONObject("personInfo");
            paramsMap.put("userName", personJson.getString("userName"));
            paramsMap.put("userPhone", personJson.getString("phone"));
            paramsMap.put("idnum", personJson.getString("idNo"));
            paramsMap.put("pripid", personJson.getString("idNo"));
            paramsMap.put("userType", "person");
            paramsMap.put("userId", personJson.getString("userId"));
        } else {
            throw new BusinessException("用户类型获取失败！");
        }
        return paramsMap;
    }

    /**
     * 请求头设置
     *
     * @param url
     * @return
     * @author zhengqiang
     * @date 2022-10-13
     **/
    private HttpHeaders getHttpHeaders(String url) {
        IrsEntSignRes res = IrsEntUtils.sign(url, "POST");

        HttpHeaders headers = new HttpHeaders();
        headers.add("X-BG-HMAC-SIGNATURE", res.getSignature());
        headers.add("X-BG-HMAC-ALGORITHM", res.getAlgorithm());
        headers.add("X-BG-HMAC-ACCESS-KEY", res.getAccessKey());
        headers.add("X-BG-DATE-TIME", res.getDateTime());
        return headers;
    }

    /**
     * 校验请求返回结果
     *
     * @param stringResponseEntity
     * @return
     * @author zhengqiang
     * @date 2022-10-13
     **/
    private JSONObject checkResponse(ResponseEntity<String> stringResponseEntity) {
        if (!stringResponseEntity.getStatusCode().is2xxSuccessful()) {
            //请求失败
            throw new BusinessException("status:" + stringResponseEntity.getStatusCodeValue() + " " + stringResponseEntity.getBody());
        }
        JSONObject result = JSON.parseObject(stringResponseEntity.getBody());
        // 请求状态码（失败,成功）
        final String errorCode = "errorCode", success = "success";
        if (result.containsKey(errorCode) && result.getString(errorCode) != null && !result.getBooleanValue(success)) {
            //业务错误
            throw new BusinessException(result.toString());
        }
        return result;
    }

    /**
     * 获取个人登录信息
     *
     * @param ssoticket
     * @return
     * @author zhengqiang
     * @date 2023-02-07
     **/
    private JSONObject getUserInfo(String ssoticket) {
        String ssotoken = ticketValidation(ssoticket);
        if (StringUtils.isBlank(ssotoken)) {
            return null;
        }
        ZlbEntUserInfoRequest param = new ZlbEntUserInfoRequest();
        param.setDatatype("json");
        param.setServicecode(serviceCode);
        param.setTime(DateUtil.getCurrentFormatTime());
        param.setToken(ssotoken);
        String sign = null;
        try {
            sign = Md5Utils.md5(serviceCode + serviceSecret + param.getTime());
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        param.setSign(sign);

        logger.info("获取浙里办用户信息请求参数: {} ", JSON.toJSONString(param));
        JSONObject jsonParam = JSONObject.parseObject(JSON.toJSONString(param));
        String result = null;
        if ("true".equals(isPrd)) { //正式环境调用转发服务
            result = forwardToZlb(jsonParam, getUserInfoUrl);
        } else {
            result = HttpUtil.createPost(getUserInfoUrl).form(jsonParam).execute().body();
        }

        if (ObjectUtils.isEmpty(result)) {
            logger.error("获取浙里办用户信息失败");
            return null;
        }
        return JSONObject.parseObject(result);
    }

    /**
     * 浙里办个人用户票据验证
     *
     * @param ssoticket
     * @return
     * @author zhengqiang
     * @date 2021-07-20
     **/
    private String ticketValidation(String ssoticket) {
        ZlbEntLoginCheckRequest param = new ZlbEntLoginCheckRequest();
        param.setDatatype("json");
        param.setServicecode(serviceCode);
        param.setTime(DateUtil.getCurrentFormatTime());
        param.setSt(ssoticket);
        String sign = null;
        try {
            sign = Md5Utils.md5(serviceCode + serviceSecret + param.getTime());
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        param.setSign(sign);

        logger.info("浙里办个人用户票据验证请求参数: {} ", JSON.toJSONString(param));
        JSONObject jsonParam = JSONObject.parseObject(JSON.toJSONString(param));
        String result = null;
        if ("true".equals(isPrd)) { //正式环境调用转发服务
            result = forwardToZlb(jsonParam, ticketValidationUrl);
        } else {
            result = HttpUtil.createPost(ticketValidationUrl).form(jsonParam).execute().body();
        }

        logger.info("浙里办个人用户票据验证返回: {} ", result);
        if (StringUtils.isBlank(result)) {
            logger.error("浙里办个人用户票据验证失败");
            return null;
        }
        JSONObject resultJson = JSONObject.parseObject(result);
        final String resultKey = "result";
        if (0 == resultJson.getIntValue(resultKey)) {
            return resultJson.getString("token");
        } else {
            logger.error("浙里办个人用户票据验证失败：" + resultJson.getString("errmsg"));
            return null;
        }
    }


    /**
     * 调用转发服务发送消息
     *
     * @param jsonParam
     * @param url
     * @return
     */
    private String forwardToZlb(JSONObject jsonParam, String url) {
        String result = null;
        try {
            jsonParam.put("zlbUrl", url);
            String userResponse = BaseUtil.post(forwardUrl, jsonParam);
            logger.info("调用转发服务返回接口:{}", userResponse);
            if (ObjectUtils.isEmpty(userResponse)) {
                return null;
            }
            Result result1 = JSONObject.parseObject(userResponse, Result.class);
            result = result1.getData().toString();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return result;
    }

}
